#pragma once
#include <thread>
#include <shared_mutex>
#include <functional>

class __THREAD__
{
	enum THREAD_STATUS
	{
		RUN, STOP, SUSPEND
	};
public:
	void start()
	{
		if (_M_status == STOP)
		{
			if (_M_p)
			{
				delete _M_p;
				_M_p = nullptr;
			}
			_M_status = RUN;
			_M_p = new std::thread(std::bind(&__THREAD__::_main_thread, this));
			if (!_M_p)
			{
				printf("NEW thread ERROR!!!!");
				return;
			}
			_M_p->detach();
		}
	}

	void stop()
	{
		_M_status = STOP;
		std::lock_guard<std::shared_mutex> _lk(_M_stop);
	}

	void suspend()
	{
		if (_M_status == RUN)
		{
			_M_supend.lock();
			_M_status = SUSPEND;
		}
	}

	void resume()
	{
		if (_M_status == SUSPEND)
		{
			_M_status = RUN;
			_M_supend.unlock();
		}
	}

protected:
	explicit __THREAD__()
		: _M_p(nullptr), _M_status(STOP) {}

	virtual ~__THREAD__() { delete _M_p; }

	virtual void _loop() = 0;

	virtual void _thread_dispose() {}
private:
	void _main_thread()
	{
		std::lock_guard<std::shared_mutex> _lk(_M_stop);
		while (true)
		{
			switch (_M_status)
			{
				case THREAD_STATUS::RUN:
				{
					_loop();
					break;
				}
				case THREAD_STATUS::SUSPEND:
				{
					_M_supend.lock();
					_M_supend.unlock();
					break;
				}
				case THREAD_STATUS::STOP:
				{
					_thread_dispose();
					return;
				}
			}
		}
	}

	std::thread* _M_p;
	enum THREAD_STATUS _M_status;
	std::shared_mutex _M_supend;
	std::shared_mutex _M_stop;
};